package com.rede.didiok.rank.restapi;


import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.rede.didiok.common.constant.conf.MessageConf;
import com.rede.didiok.common.constant.conf.RedisConf;
import com.rede.didiok.common.constant.conf.SQLConf;
import com.rede.didiok.common.constant.conf.SysConf;
import com.rede.didiok.common.constant.global.Constants;
import com.rede.didiok.common.constant.global.ECode;
import com.rede.didiok.common.domainEvent.EventAction;
import com.rede.didiok.common.dto.rank.RankMemberDto;
import com.rede.didiok.common.enums.AuditStatusEnum;
import com.rede.didiok.common.enums.PublishEnum;
import com.rede.didiok.common.enums.StatusEnum;
import com.rede.didiok.common.exception.exceptionType.BusinessException;
import com.rede.didiok.common.feign.AdminFeignClient;
import com.rede.didiok.common.feign.FileFeignClient;
import com.rede.didiok.common.feign.PayFeignClient;
import com.rede.didiok.common.feign.UserFeignClient;
import com.rede.didiok.common.holder.RequestHolder;
import com.rede.didiok.common.utils.IpUtils;
import com.rede.didiok.common.utils.JsonUtils;
import com.rede.didiok.common.utils.ResultUtil;
import com.rede.didiok.common.utils.StringUtils;
import com.rede.didiok.common.utils.business.DomainEventUtil;
import com.rede.didiok.common.utils.business.WebUtil;
import com.rede.didiok.rank.entity.RankMemberEntity;
import com.rede.didiok.rank.service.RankMemberService;

/**
 * 文章详情 RestApi
 *
 * @author Rede
 * @date 2023-09-04
 */
@RestController
@RefreshScope
@RequestMapping("/content")
@Api(value = "榜单成员详情相关接口", tags = {"榜单成员详情相关接口"})
@Slf4j
public class RankMemberContentRestApi {
    @Autowired
    private WebUtil webUtil;
    @Autowired
    private RankMemberService rankMemberService;
    @Resource
    private FileFeignClient fileFeignClient;
    @Resource
    private PayFeignClient payFeignClient;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private AdminFeignClient adminFeignClient;
    @Autowired
    private UserFeignClient userFeignClient;
    @Value(value = "${RANK.ORIGINAL_TEMPLATE}")
    private String ORIGINAL_TEMPLATE;
    @Value(value = "${RANK.REPRINTED_TEMPLATE}")
    private String REPRINTED_TEMPLATE;
    /**
     * 领域事件工具类
     */
    @Resource
    private DomainEventUtil domainEventUtil;

    @ApiOperation(value = "通过Uid获取博客内容", notes = "通过Uid获取博客内容")
    @GetMapping("/getRankMemberByUid")
    public String getRankMemberByUid(@ApiParam(name = "uid", value = "博客UID", required = false) @RequestParam(name = "uid", required = false) String uid,
                               @ApiParam(name = "isLazy", value = "是否开启图片懒加载", required = false) @RequestParam(name = "isLazy", required = false, defaultValue = "0") String isLazy,
                               @ApiParam(name = "oid", value = "博客OID", required = false) @RequestParam(name = "oid", required = false, defaultValue = "0") Integer oid) {
        String userUid = RequestHolder.getUserUid();
        HttpServletRequest request = RequestHolder.getRequest();
        String ip = IpUtils.getIpAddr(request);
        if (StringUtils.isEmpty(uid) && oid == 0) {
            log.error("[getRankMemberByUid] 文章ID不能为空");
            return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
        }

        RankMemberEntity rankMember = null;

        // TODO 可以使用多线程：查询活动信息和用户信息，同时进行

        rankMember = rankMemberService.getRankMemberDetailInfoById(uid, oid);
        if(rankMember == null) {
            log.error("[getRankMemberByUid] 抱歉，文章不存在！, rankMemberOid: {}, rankMemberUid: {}", oid, uid);
            throw new BusinessException("抱歉，文章不存在！");
        }

        // 判断是否是登录的用户在预览自己的博客
        boolean isMyBlog = false;
        if (StringUtils.isNotEmpty(userUid)) {
            if (userUid.equals(rankMember.getCreateUserUid())) {
                isMyBlog = true;
            }
//            else {
//                // 判断当前用户是否被附身操作
//                Integer count = adminFeignClient.countAdminByUserUid(userUid);
//                isMyBlog = count > 0;
//            }
        }

        // 自己的博客，可以预览进行未发布的预览，否则无法打开
        if (!isMyBlog && (rankMember.getStatus() == StatusEnum.DISABLED ||
                PublishEnum.NO_PUBLISH.equals(rankMember.getIsPublish()) ||
                !AuditStatusEnum.AGREE.equals(rankMember.getAuditStatus()))) {
            log.error("[getRankMemberByUid] 文章暂未发布或已被删除， rankMemberUid: {}", rankMember.getUid());
            return ResultUtil.result(ECode.ERROR, MessageConf.RANK_MEMBER_IS_DELETE);
        }

        // 设置博客信息
        rankMember = rankMemberService.setRankMemberInfoWithUser(rankMember);

        //从Redis取出数据，判断该用户是否点击过
        String jsonResult = stringRedisTemplate.opsForValue().get("RANK_MEMBER_CLICK:" + ip + "#" + rankMember.getUid());
        if (StringUtils.isEmpty(jsonResult)) {
            //给博客点击数增加
            Integer clickCount = rankMember.getClickCount() + 1;
            rankMember.setClickCount(clickCount);
            rankMember.updateById();
            //将该用户点击记录存储到redis中, 24小时后过期
            stringRedisTemplate.opsForValue().set(RedisConf.RANK_MEMBER_CLICK + Constants.SYMBOL_COLON + ip + Constants.SYMBOL_WELL + rankMember.getUid(), rankMember.getClickCount().toString(),
                    24, TimeUnit.HOURS);

            // 过滤掉内容和简介【拷贝个对象，过滤掉无效信息】
            RankMemberEntity tempBlog = new RankMemberEntity();
            tempBlog.setUid(rankMember.getUid());
            tempBlog.setCreateUserUid(rankMember.getCreateUserUid());
            // 发布首次访问的事件
            RankMemberDto dto = new RankMemberDto();
            BeanUtils.copyProperties(tempBlog, dto);
            domainEventUtil.publishEvent(EventAction.RANK_MEMBER_VISIT, dto);
        }

        // 判断是否开启图片懒加载
        if (Constants.STR_ONE.equals(isLazy)) {
            String blogContent = rankMember.getContent();
            if (StringUtils.isNotEmpty(blogContent)) {
                // 定义正则表达式，匹配img标签的src属性
                Pattern pattern = Pattern.compile("<img\\s+[^>]*?\\bsrc\\s*=\\s*[\'\"]?([^\'\"]+)[\'\"]?");
                // 将匹配到的img标签的src属性替换为data-src
                Matcher matcher = pattern.matcher(blogContent);
                String newString = matcher.replaceAll("<img data-src=\"$1\"");
                rankMember.setContent(newString);
            }
        }

        // 查询当前活动的玩家报名人数和领队报名人数
        String jsonStr = payFeignClient.getApplyUserNumByResourceUid(rankMember.getUid());
        Map<String, Object> resultTempMap = JsonUtils.jsonToMap(jsonStr);
        if (resultTempMap.get(SysConf.CODE) != null && SysConf.SUCCESS.equals(resultTempMap.get(SysConf.CODE).toString())) {
            Map<String, Object> amountMap = (Map<String, Object>) resultTempMap.get(SysConf.DATA);
            double totalApplyUserNumD = amountMap.get(SQLConf.AMOUNT) == null? 0: (Double) amountMap.get(SQLConf.AMOUNT);
            int totalApplyUserNumInt = (int) totalApplyUserNumD;
            rankMember.setTotalApplyUserNum(totalApplyUserNumInt);
            // 是否报名人数已满
            rankMember.setIsApplyUserNumFull(totalApplyUserNumInt >= rankMember.getAllowPeopleNum() ? 1 : 0);
            // 是否领队人数已满
            double totalApplyLeaderD = amountMap.get(SQLConf.LEADER_AMOUNT) == null? 0: (Double) amountMap.get(SQLConf.LEADER_AMOUNT);
            int totalApplyLeaderNum = (int) totalApplyLeaderD;
            rankMember.setTotalApplyLeaderNum(totalApplyLeaderNum);
            rankMember.setIsLeaderUserNumFull(totalApplyLeaderNum >= rankMember.getAllowLeaderNum() ? 1 : 0);
        }

        // 校验是否满足访问条件
//        rankMemberService.checkVisitAuth(rankMember);

        return ResultUtil.result(SysConf.SUCCESS, rankMember);
    }

    @ApiOperation(value = "通过Uid获取榜单成员点赞数", notes = "通过Uid获取榜单成员点赞数")
    @GetMapping("/getRankMemberPraiseCountByUid")
    public String getRankMemberPraiseCountByUid(@ApiParam(name = "uid", value = "榜单成员UID", required = false) @RequestParam(name = "uid", required = false) String uid) {
        return ResultUtil.result(SysConf.SUCCESS, rankMemberService.getRankMemberPraiseCountByUid(uid));
    }
//
//    @BussinessLog(value = "通过Uid给博客点赞", behavior = BehaviorEnum.BLOG_PRAISE)
//    @ApiOperation(value = "通过Uid给博客点赞", notes = "通过Uid给博客点赞")
//    @GetMapping("/praiseBlogByUid")
//    public String praiseBlogByUid(@ApiParam(name = "uid", value = "博客UID", required = false) @RequestParam(name = "uid", required = false) String uid) {
//        if (StringUtils.isEmpty(uid)) {
//            return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
//        }
//        return rankMemberService.praiseRankMemberByUid(uid);
//    }

    @ApiOperation(value = "根据成员等级Uid获取相关的榜单成员", notes = "根据成员等级Uid获取相关的榜单成员")
    @GetMapping("/getSameRankMemberByGradeUid")
    public String getSameRankMemberByGradeUid(@ApiParam(name = "gradeUid", value = "榜单成员等级UID", required = true) @RequestParam(name = "gradeUid", required = true) String gradeUid,
                                      @ApiParam(name = "currentPage", value = "当前页数", required = false) @RequestParam(name = "currentPage", required = false, defaultValue = "1") Long currentPage,
                                      @ApiParam(name = "pageSize", value = "每页显示数目", required = false) @RequestParam(name = "pageSize", required = false, defaultValue = "10") Long pageSize) {
        if (StringUtils.isEmpty(gradeUid)) {
            return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
        }
        return ResultUtil.result(SysConf.SUCCESS, rankMemberService.getSameRankMemberByGradeUid(gradeUid));
    }

    @ApiOperation(value = "根据标签Uid获取相关的博客", notes = "根据标签Uid获取相关的博客")
    @GetMapping("/getSameRankMemberByTagUid")
    public String getSameRankMemberByTagUid(@ApiParam(name = "tagUid", value = "博客标签UID", required = true) @RequestParam(name = "tagUid", required = true) String tagUid,
                                              @ApiParam(name = "currentPage", value = "当前页数", required = false) @RequestParam(name = "currentPage", required = false, defaultValue = "1") Long currentPage,
                                              @ApiParam(name = "pageSize", value = "每页显示数目", required = false) @RequestParam(name = "pageSize", required = false, defaultValue = "10") Long pageSize) {
        if (StringUtils.isEmpty(tagUid)) {
            return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
        }
        return ResultUtil.result(SysConf.SUCCESS, rankMemberService.getSameRankMemberByTagUid(tagUid));
    }

    @ApiOperation(value = "根据rankMemberUid获取相关的榜单成员", notes = "根据rankMemberUid获取相关的榜单成员")
    @GetMapping("/getSameRankMemberByRankMemberUid")
    public String getSameRankMemberByRankMemberUid(@ApiParam(name = "memberUid", value = "榜单成员UID", required = true) @RequestParam(name = "memberUid", required = true) String memberUid,
                                                   @ApiParam(name = "rankUid", value = "分类UID", required = true) @RequestParam(name = "rankUid", required = true) String rankUid) {
        if (StringUtils.isEmpty(memberUid)) {
            return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
        }
        List<RankMemberEntity> memberList = rankMemberService.getSameRankMemberByRankMemberUid(memberUid, rankUid);
        IPage<RankMemberEntity> pageList = new Page<>();
        pageList.setRecords(memberList);
        return ResultUtil.result(SysConf.SUCCESS, pageList);
    }

    @ApiOperation(value = "根据BlogUid下载博客", notes = "根据BlogUid下载博客")
    @GetMapping("/downloadRankMember")
    public String downloadRankMember(@ApiParam(name = "memberUid", value = "博客UID", required = true) @RequestParam(name = "memberUid", required = true) String memberUid) {
        if (StringUtils.isEmpty(memberUid)) {
            return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
        }
        return ResultUtil.successWithData(rankMemberService.downloadRankMember(memberUid));
    }

    /**
     * 设置榜单成员标题图
     *
     * @param
     */
    private void setPhotoListByRankMember(RankMemberEntity rankMember) {
        //获取标题图片
        if (rankMember != null && !StringUtils.isEmpty(rankMember.getFileUid())) {
            String result = fileFeignClient.getPicture(rankMember.getFileUid(), Constants.SYMBOL_COMMA);
            List<String> picList = webUtil.getPicture(result);
            if (picList != null && picList.size() > 0) {
                rankMember.setPhotoList(picList);
            }
        }
    }

}

